iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 5
0
Security

資訊安全的美味雜炊系列 第 5

[Day5] - SQL injection (1)

  • 分享至 

  • xImage
  •  

Day5 - SQL injection (1)

前言

  • 這應該是web security最經典的注入攻擊了,而且最為廣泛也淺顯易懂
  • 筆者會將SQL injection分成兩天來討論,今天會先介紹SQL injection是甚麼及預防的姿勢,明天則會介紹SQL injection的種類

介紹

  • 發生在後端與資料庫之間的安全漏洞。駭客在輸入的字串中能夠夾帶SQL指令,並沒有過濾字串

  • 通常是使用字串串聯方式來構成SQL的指令,若又在連線的時候使用權限過大的帳戶(工程師偷懶使用root或sa連接資料庫XD),甚至可以Get Shell

  • SQL-injection最經典的一部漫畫

    1. 媽媽接到電話,你好,我這邊是你兒子的學校,我們電腦出了點狀況

    2. oh, 他用壞了甚麼東西嗎,媽媽問。 校方說: 可以這麼說

    3. 校方說: 你真的把你兒子取名為Robert'); DROP TABLE Students; --嗎?
      媽媽說: 是的,我們都叫他寶貝table

    4. 校方回說: 我們今年的學生資料都不見了,希望你覺得滿意。
      媽媽說: 希望你以後會記得把寫進Table的資料清掉

經典到不能再經典的例子

  • 網站的登入驗證
sql = "SELECT * FROM users WHERE (name = '" + username + "') and (pw = '"+ password +"');";
db->execute(sql);
  • 這時駭客輸入在登入介面分別輸入
  1. username: ' OR 1=1 --
  2. password: ' OR 1=1 --
  • 組合完會像這樣
    • name = '1' OR 1=1
      • 前面的語句就算邏輯錯誤,後面的1=1條件恆為True,False or True = True
      • 因此,後面兩個OR條件後的句子,都恆為True,進而達到沒有帳號密碼就能登入網站的尷尬情況
    • --為註解,目的是將無用的語句去掉
      • MySQL還有其他註解像是#, /*
sql = "SELECT * FROM users WHERE (name = '' OR 1=1 --') and (pw = '' OR 1=1 --');";
db->execute(sql);

搭配漫畫的例子

  • 將password改成: ' OR 1=1; DROP TABLE Students; --
  • 很恭喜,你的整張表就直接不見囉
sql = "SELECT * FROM users WHERE (name = '' OR 1=1 --') and (pw = '' OR 1=1; DROP TABLE users --');";
db->execute(sql);

如何避免?

  • 單純的過濾輸入,但駭客的手法百百種,他們能在有限的狀況下,又找出新的方法可以繞過

    • 恩,後面講的靶場就是模擬駭客在受限的各種字元過濾下,盡情的絞盡腦汁繞過
  • 比較安全的作法

    • 使用prepared statements(預先準備SQL語句)搭配parameterized queries(參數化的查詢)
    • 透過預先準備SQL語句與參數化查詢,能讓資料庫知道說要插入甚麼值作為甚麼功用,就不會對甚麼OR 1=1 --和空的密碼做query,或是用;截斷語句做其他事情

以PHP為例,可以使用

  • PHP Data Objects(PDO)寫法
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

$stmt->execute([ 'name' => $name ]);

foreach ($stmt as $row) {
    // Do something with $row
}
  • MySQLi (for MySQL):
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'

$stmt->execute();

$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // Do something with $row
}

參考自: https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php
參考自: https://www.it-swarm.dev/zh/sql/%E5%8F%82%E6%95%B0%E5%8C%96%E8%AF%AD%E5%8F%A5%E5%8F%AF%E4%BB%A5%E5%81%9C%E6%AD%A2%E6%89%80%E6%9C%89sql%E6%B3%A8%E5%85%A5%E5%90%97%EF%BC%9F/940507514/

分享有趣的題外話 - 濾單引號就夠了ㄇ

我百分之百贊同「置換單引號不能杜絕SQL Injection,在某些特殊情境下會被攻破」,但在沒有強力佐證的情況下要說 「哼!換掉單引號根本沒屁用」 則略嫌浮誇。

SQL-injection 靶場

  • https://hackme.inndy.tw/

    • 這邊有一系列的SQL injection題目
  • DVWA

    • 經典到不行的靶場,
  • http://los.eagle-jump.org

    • 能夠從初學者漸進到進階者的SQL injection的好靶場,但筆者最近打開似乎網站是關閉的,不過還是列在這裡

上一篇
[Day4] - XSS(Cross site scripting) 簡單範例
下一篇
[Day6] - SQL injection (2)
系列文
資訊安全的美味雜炊30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言